﻿using DocumentFormat.OpenXml.Lite.Core.Interfaces;
using DocumentFormat.OpenXml.Lite.Core.Office;
using DocumentFormat.OpenXml.Lite.DrawingML.Chart.Elements;
using DocumentFormat.OpenXml.Lite.DrawingML.Chart.Properties;
using DocumentFormat.OpenXml.Lite.DrawingML.Color;
using DocumentFormat.OpenXml.Lite.DrawingML.Geometry;
using DocumentFormat.OpenXml.Lite.DrawingML.Geometry.Properties;
using DocumentFormat.OpenXml.Lite.DrawingML.Text;
using DocumentFormat.OpenXml.Lite.DrawingML.Text.Properties;
using DocumentFormat.OpenXml.Lite.Shared;
using DocumentFormat.OpenXml.Lite.Xml;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using IO = System.IO;

namespace DocumentFormat.OpenXml.Lite.DrawingML.Chart
{
    [XmlRoot("chartSpace", Namespace = Constants.Chart)]
    public class ChartSpace : XmlSerializable, ISerializable, IDrawingElement
    {
        #region Elements

        [Optional]
        [XmlElement("date1904", Namespace = Constants.Chart)]
        public NullableValue<bool> Date1904Format { get; set; }

        [Optional]
        [XmlElement("lang", Namespace = Constants.Chart)]
        public RequiredValue<string> EditingLanguage { get; set; }

        [Optional]
        [XmlElement("roundedCorners", Namespace = Constants.Chart)]
        public NullableValue<bool> RoundedCorners { get; set; }

        [Optional]
        [XmlElement("style", Namespace = Constants.Chart)]
        public RequiredValue<byte> Style { get; set; }

        [Optional]
        [XmlElement("clrMapOvr", Namespace = Constants.Chart)]
        public ColorMapOverride ColorMapOverride { get; set; }

        [Optional]
        [XmlElement("pivotSource", Namespace = Constants.Chart)]
        public PivotSource PivotSource { get; set; }

        [Optional]
        [XmlElement("protection", Namespace = Constants.Chart)]
        public Protection Protection { get; set; }

        [Optional]
        [XmlElement("chart", Namespace = Constants.Chart)]
        public Chart Chart { get; set; }

        [Optional]
        [XmlElement("spPr", Namespace = Constants.Chart)]
        public ShapeProperties ShapeProperties { get; set; }

        [Optional]
        [XmlElement("txPr", Namespace = Constants.Chart)]
        public TextProperties TextProperties { get; set; }

        [Optional]
        [XmlElement("externalData", Namespace = Constants.Chart)]
        public ExternalData ExternalData { get; set; }

        [Optional]
        [XmlElement("userShapes", Namespace = Constants.Chart)]
        public UserShapes UserShapes { get; set; }

        [Optional]
        [XmlElement("printSettings", Namespace = Constants.Chart)]
        public PrintSettings PrintSettings { get; set; }

        [Optional]
        [XmlElement("extLst", Namespace = Constants.Chart)]
        public ExtensionList ExtensionList { get; set; }

        #endregion

        [XmlNamespaceDeclarations]
        public XmlSerializerNamespaces Namespaces { get; set; }

        public ChartSpace()
        {
            Namespaces = new XmlSerializerNamespaces();
            Namespaces.Add("a", Constants.Main);
            Namespaces.Add("c", Constants.Chart);
            //Namespaces.Add("xml", Constants.Xml);
            Namespaces.Add("r", Constants.Relationship);
        }

        #region ISerializable Members

        public byte[] Serialize()
        {
            XmlSerializer serializer = new XmlSerializer(this.GetType());
            using (var stream = new IO.MemoryStream())
            {
                using (var writer = new IO.StreamWriter(stream, Encoding.UTF8))
                {
                    using (var xwriter = XmlWriter.Create(writer))
                    {
                        xwriter.WriteStartElement("c", "chartSpace", Constants.Chart);
                        foreach (var ns in Namespaces.ToArray())
                        {
                            if (ns.Name != "")
                            {
                                xwriter.WriteAttributeString("xmlns", ns.Name, null, ns.Namespace);
                            }
                        }
                        this.WriteXml(xwriter);
                    }
                    return stream.ToArray();
                }
            }
        }

        public void Deserialize(System.IO.Stream content)
        {
            using (var reader = XmlReader.Create(content))
            {
                reader.ReadToDescendant("chartSpace", Constants.Chart);
                for (int i = 0; i < reader.AttributeCount; ++i)
                {
                    string s = reader.GetAttribute(i);
                    if (Constants.GetDefaultPrefix(s) != string.Empty)
                    {
                        Namespaces.Add(Constants.GetDefaultPrefix(s), s);
                    }
                }
                this.ReadXml(reader);
            }
        }

        #endregion
    }
}
